/**
 * 创建时间:2019-6-6
 * 创建人:TY-sunxiongtong
 */

// 创建一个对象 存储所有的图片
window.onload = function(){
	//canvas画布
	var canvas = document.getElementById("canvas");
	var ctx = canvas.getContext("2d");
	var musicElem = document.getElementById("musicBg");
	var scoreElem = document.getElementById('score');
	var over = document.getElementById('over');
	
	var gameover = false; //游戏是否结束
	var suspend = false; //暂停
	var planeWidth = 35; //飞机宽
	var planeHeight = 85; //飞机高
	var suspend = false; //游戏暂停
	
	var loadingImg = {
		bgImg: "https://top-cdn.aax6.cn/miniprogramimages/mnyyc/chxxl/background1.png",
		bullet:"https://top-cdn.aax6.cn/miniprogramimages/mnyyc/chxxl/bullet3.png",
		enemy1:"https://top-cdn.aax6.cn/miniprogramimages/mnyyc/chxxl/enemy1.png",
		enemy2:"https://top-cdn.aax6.cn/miniprogramimages/mnyyc/chxxl/enemy2.png",
		enemy3:"https://top-cdn.aax6.cn/miniprogramimages/mnyyc/chxxl/enemy3.png",
		herofly: "https://top-cdn.aax6.cn/miniprogramimages/mnyyc/chxxl/herofly1.png",
		musicOpen:"https://top-cdn.aax6.cn/miniprogramimages/mnyyc/chxxl/musicOpen.png",
		musicMute:"https://top-cdn.aax6.cn/miniprogramimages/mnyyc/chxxl/musicMute.png"
	}
	
	//声明预加载函数！！！！
	function loading(loadingImg, succFn) {
		var imgs = {};//加载完成的图片的存储位置
		// imgs对象
		var index = 0;//加载的图片数
		var allNum = 0;//图片的总数
		// for in 用于数组或者对象的属性进行循环操作 
		for (var i in loadingImg) {
			allNum++;
		}
		//初始化的i为0 ，循环检查对象中的元素
		// 打印出一共多少的元素
		// 初始化，遍历对象中其他的属性
		for (var j in loadingImg) {
			// 创建img标签
			imgs[j] = new Image();
			// 为照片符上路径
			imgs[j].src = loadingImg[j];
			// 图片加载
			imgs[j].onload = function () {
				index++;
				if (index >= allNum) {
					//加载完成
					succFn();
				}
			}
		}
	}
	
	//游戏与打飞机游戏相似，为取名方便 优益C--飞机  食物--敌人
	var planeImg = new Image();
	planeImg.src = loadingImg.herofly;
	
	//结束游戏
	over.addEventListener('click',function(){
		gameover = true;
	});
	
	// 初始化资源
	var music = new Audio();
	var musicPlay = true;
	music.src = 'https://top-cdn.aax6.cn/front-end/project/mengniu/images/youyic/boom.mp3';
	music.load();
	music.bol = false;
	musicElem.onclick = function(){
		if(musicPlay){
			musicPlay = false;
			musicElem.src = loadingImg.musicMute;
		}else{
			musicPlay = true;
			musicElem.src = loadingImg.musicOpen;
		}
	}
	//屏幕大小
	var screenWidth = canvas.width = window.innerWidth;
	var screenHeight = canvas.height = window.innerHeight;
	
	over.addEventListener('touchend', function() {
		suspend = true;
	})
	
	//背景
	var bgImg = new Image();
	bgImg.src = loadingImg.bgImg;
	
	/**
	 * 背景类
	 */
	function Bg() {
		this.w = screenWidth;
		this.h = screenHeight;
		this.x = 0;
		this.y = 0;
	}
	
	Bg.prototype.draw = function() {
		ctx.drawImage(bgImg, this.x, this.y, canvas.width, canvas.height);
		ctx.drawImage(bgImg, this.x, this.y - canvas.height, canvas.width, canvas.height)
	}
	
	var bg = new Bg();
	
	/**
	 * 飞机类
	 */
	function Plane() {
		this.w = planeWidth;
		this.h = planeHeight;
		this.x = (canvas.width - planeWidth) / 2; //飞机初始横坐标
		this.y = (canvas.height - planeHeight); //飞机的初始纵坐标
		this.boom = false; //飞机是否消亡
		this.index = 0; //控制飞机消亡图片下标
		this.touch = false; //用户是否触碰
	}
	
	Plane.prototype.draw = function() {
		if (!this.boom) {
			ctx.drawImage(planeImg, 0, 0, planeWidth * 2, planeHeight * 2, this.x, this.y, this.w, this.h);
		}
	}
	
	Plane.prototype.setAirPosAcrossFingerPosZ = function(x, y) {
		let disX = x - this.w / 2;
		let disY = y - this.h / 2;
	
		if (disX < 0)
			disX = 0;
	
		else if (disX > screenWidth - this.w)
			disX = screenWidth - this.w;
	
		if (disY <= 0)
			disY = 0;
	
		else if (disY > screenHeight - this.h)
			disY = screenHeight - this.h
	
		this.x = disX;
		this.y = disY;
	}
	
	var plane = new Plane();

	var frameNum = 0;
	var bullets = [];
	var enemys = {
		"enemys1": [],
		"enemys2": [],
		"enemys3": [],
	};
	
	//敌人速度
	var EnemySpeed = 2;
	var BULLET_WIDTH = 30;
	var BULLET_HEIGHT = 27;
	var pool = new Pool();
	var bombBol = false;
	var score = 0; //分数
	
	/**
	 * @description 主函数,用来所有的页面事件
	 */
	function main() {
		frameNum++;
		bg.draw();
		plane.draw();
	
		bullets.forEach(function(item) {
			item.update();
			item.drawToCanvas(ctx);
		})
	
		//子弹
		if (frameNum % 10 == 0) {
			var bullet = pool.getItemByClass('bullet', Bullet)
			bullets.push(bullet);
			bullet.reset();
			bullet.update();
			bullet.drawToCanvas(ctx);
		}
	
		//敌机
		if (frameNum % 50 == 0) {
			createEnemy();
		}
	
		for (var key in enemys) {
			enemys[key].forEach(function(item) {
				item.update();
				item.drawToCanvas();
				item.crash();
				if (bombBol) {
					bombBol = false;
				}
			})
		}
	}
	
	/**
	 * @description 动画函数
	 */
	function animate() {
		main();
		if (gameover || suspend) {
			//游戏结束或者游戏暂停
			window.cancelAnimationFrame(animate);
			wx.miniProgram.redirectTo({
				url: '/pages/planeGame/settlement/settlement?score=' + score
			});
			return;
		} else {
			window.requestAnimationFrame(animate);
		}
	}
	
	loading(loadingImg,animate);
	/**
	 * @description 对象池使用，提升页面性能
	 */
	function Pool() {
		this['poolDic'] = {}
	}
	
	/**
	 * 根据对象标识符
	 * 获取对应的对象池
	 */
	Pool.prototype.getPoolBySign = function(name) {
		return this['poolDic'][name] || (this['poolDic'][name] = [])
	}
	
	/**
	 * 根据传入的对象标识符，查询对象池
	 * 对象池为空创建新的类，否则从对象池中取
	 */
	Pool.prototype.getItemByClass = function(name, className) {
		var pool = this.getPoolBySign(name)
		
		var result = (pool.length ?
			pool.shift() :
			new className())
		
		return result
	}
	
	/**
	 * 将对象回收到对象池
	 * 方便后续继续使用
	 */
	Pool.prototype.recover = function(name, instance) {
		this.getPoolBySign(name).push(instance)
	}
	
	/**
	 * @description 判断手指是否在飞机上
	 * @param {Number} x: 手指的X轴坐标
	 * @param {Number} y: 手指的Y轴坐标
	 */
	function checkIsFingerOnAir(x, y) {
		const deviation = 30; //偏差可以有30像素
		const px = plane.x;
		const py = plane.y;
		const pw = plane.w;
		const ph = plane.h;
	
		if (!music.bol) {
			music.load();
			music.bol = true;
		}
	
		return !!(x >= px - deviation &&
			y >= py - deviation &&
			x <= px + pw + deviation &&
			y <= py + ph + deviation)
	}
	
	/**
	 * 随机函数
	 */
	function rand(min, max) {
		return parseInt(Math.random() * (max - min + 1) + min);
	}
	
	document.addEventListener('touchstart', ((e) => {
		// e.preventDefault()
	
		let x = e.touches[0].clientX
		let y = e.touches[0].clientY
		
		
		if(e.touches.length == 2){
			let x1 = e.touches[1].clientX;
			let y1 = e.touches[1].clientY;
			
			if(x1>=0 && x1<=100 && y1>=0 && y1 <=100){
				musicElem.click();
			}
			
		}
		
		if (checkIsFingerOnAir(x, y)) {
			plane.touched = true
			plane.setAirPosAcrossFingerPosZ(x, y)
		}
	
	}).bind(plane))
	
	canvas.addEventListener('touchmove', ((e) => {
		e.preventDefault()
	
		let x = e.touches[0].clientX
		let y = e.touches[0].clientY
		
		if (plane.touched)
			plane.setAirPosAcrossFingerPosZ(x, y)
	}).bind(plane))
	
	canvas.addEventListener('touchend', ((e) => {
		e.preventDefault()
	
		plane.touched = false
	}).bind(plane))
	
	/**
	 * @description 子弹类
	 */
	function Bullet(x, y) {
		this.img = new Image()
		this.img.src = loadingImg.bullet
	
		//大小
		this.w = BULLET_WIDTH
		this.h = BULLET_HEIGHT
	
		//速度
		this.speed = 7
		//是否是创建时刻
		this.bol = true;
		this.reset();
	}
	
	Bullet.prototype.reset = function() {
		this.x = plane.x + (plane.w - BULLET_WIDTH) / 2
		this.y = plane.y - BULLET_HEIGHT
		//是否显示
		this.visible = true
		if (this.bol) {
			this.s = this.y - 800;
			this.bol = false;
		}
	}
	
	Bullet.prototype.drawToCanvas = function(ctx) {
		if (!this.visible) {
			return
		}
	
		ctx.drawImage(this.img, this.x, this.y, this.w, this.h)
	}
	
	Bullet.prototype.update = function() {
		this.y -= this.speed
		// 超出屏幕外回收自身
	
		if (this.y < this.s) {
			this.bol = true;
			this.removeBullets(this)
		}
	}
	
	Bullet.prototype.removeBullets = function(bullet) {
		let temp = bullets.shift()
	
		temp.visible = false
	
		pool.recover('bullet', bullet)
	}
	
	function createEnemy() {
		var r = rand(1, 100);
		var enemyImg = new Image();
		if (r > 0 && r <= 40) {
			//小号敌机
			enemyImg.src = loadingImg.enemy1;
			//爆炸时图片的个数
			enemyImg.length = 3;
			//绘制的宽度
			enemyImg.w = 54;
			//绘制的高度
			enemyImg.h = 49;
			enemyImg.b = 2;
			enemyImg.str = 'enemys1';
			enemyImg.bombIndex = 2;
			enemyImg.index = 0;
			var enemy = pool.getItemByClass(enemyImg.str, Enemy.bind(null, enemyImg))
			enemys.enemys1.push(enemy);
		} else if (r > 40 && r <= 70) {
			//中号飞机
			enemyImg.src = loadingImg.enemy2;
			enemyImg.length = 6;
			enemyImg.w = 80;
			enemyImg.h = 72;
			enemyImg.b = 2;
			enemyImg.str = 'enemys2';
			enemyImg.bombIndex = 3;
			enemyImg.index = 0;
			var enemy = pool.getItemByClass(enemyImg.str, Enemy.bind(null, enemyImg))
			enemys.enemys2.push(enemy);
		} else {
			//大号飞机
			enemyImg.src = loadingImg.enemy3;
			enemyImg.length = 10;
			enemyImg.w = 73;
			enemyImg.h = 58;
			enemyImg.b = 2;
			enemyImg.str = 'enemys3';
			enemyImg.bombIndex = 5;
			enemyImg.index = 0;
			var enemy = pool.getItemByClass(enemyImg.str, Enemy.bind(null, enemyImg))
			enemys.enemys3.push(enemy);
		}
		//重置初始状态
		enemy.reset(enemyImg);
	}
	
	/**
	 * 敌人类
	 */
	function Enemy(enemy) {
		this.bombNum = 0; //爆炸经过了多少帧
		this.length = enemy.length * 5 //每5帧过一幅图
		this.crashBol = false;
		this.enemy = enemy;
		this.enemy.index = 0;
		this.bombIndex = enemy.bombIndex;
		this.w = enemy.w;
		this.h = enemy.h;
		this.xd = 0;
		//根据图片比例截取
		this.b = enemy.b;
		//累计次数，到自己的次数会爆炸
		this.index = 0;
		this.stop = false;
		//是否首次创建
		this.bol = true;
		this.visible = true;
		this.reset(enemy)
	}
	
	Enemy.prototype.reset = function(enemy) {
		this.x = rand(0, screenWidth - this.w);
		this.y = -this.h;
		this.cutX = 0;
		this.cutY = 0;
		this.visible = true;
		this.index = 0;
		// 食物消亡图片变小，xd用来指定小了多少像素
		this.xd = 0;
		this.enemy.index = 0;
		if (this.bol) {
			this.s = this.h + 1500;
			this.bol = false;
		}
	}
	Enemy.prototype.drawToCanvas = function() {
		if(this.enemy.src.indexOf('enemy3')>-1){
			if(this.enemy.index == 2){
				this.xd = 5;
			}
			if(this.enemy.index == 3){
				this.xd = 20;
			}
			if(this.enemy.index == 4){
				this.xd = 30;
			}
		}
		if(this.enemy.src.indexOf('enemy2')>-1){
			if(this.enemy.index == 1){
				this.xd = 10;
			}
			if(this.enemy.index == 2){
				this.xd = 15;
			}
			if(this.enemy.index == 3){
				this.xd = 25;
			}
		}
		// ctx.fillRect(this.x+this.xd, this.y, this.w-this.xd, this.h)
		ctx.drawImage(this.enemy, this.cutX, this.cutY, this.w * this.b, this.h * this.b, this.x, this.y, this.w, this.h);
	}
	Enemy.prototype.update = function() {
		// if(!this.stop){
		this.y += EnemySpeed;
		// }
		if (this.y >= screenHeight - this.h) {
			gameover = true;
		}
		if (this.y > this.s) {
			this.bol = true;
		}
	}
	// 音乐
	Enemy.prototype.music = function() {
		if(musicPlay){
			music.currentTime = 0;
			music.play();
		}
	}
	Enemy.prototype.removeBullets = function(str,enemy) {
		pool.recover(str, enemy)
	}
	
	Enemy.prototype.bomb = function() {
		for (var i = 0; i < enemys[this.enemy.str].length; i++) {
			if (this == enemys[this.enemy.str][i]) {
				var el = enemys[this.enemy.str].splice(i, 1);
				bombBol = true;
			}
		}
	}
	Enemy.prototype.crash = function() {
		for (var i = 0; i < bullets.length; i++) {
			if (crash(this, plane)) {
				gameover = true;
				return;
			}
			if (crash(this, bullets[i]) && !this.crashBol && this.y > 0) {
				this.cutX += this.w * this.b;
				score++;
				if (score == 80 || score == 120 || score == 160 || score == 200 || score == 240 || score == 280 || score ==
					320 || score == 360 || score == 400 || score == 440 || score == 480 || score == 520) {
					EnemySpeed++;
				}
				scoreElem.innerHTML = score;
				this.enemy.index ++;
				bullets[i].visible = false;
				bullets.splice(i, 1);
				this.index++;
				if (this.index >= this.bombIndex) {
					this.music();
					this.crashBol = true;
				}
			}
		}
	
		if (this.crashBol) {
			var str = this.enemy.str;
			var text = '';
			var div = document.createElement('div');
			if (str === 'enemys1') {
				text = "+2";
			} else if (str === 'enemys2') {
				text = "+3";
			} else {
				text = "+5";
			}
			div.className = 'addScore';
			div.innerHTML = text;
			div.style.left = this.x + this.w + 'px';
			div.style.top = this.y + 'px';
	
			document.body.appendChild(div);
			setTimeout(function() {
				div.style.opacity = 0;
				setTimeout(function() {
					document.body.removeChild(div);
				}, 2000)
			},0)
			this.crashBol = false;
			this.removeBullets(this.enemy.str,this)
			this.bomb();
		}
	}
	
	/**
	 * 简单的碰撞检测，方形
	 */
	function crash(obj1, obj2) {
		var l1 = obj1.x+obj1.xd;
		var r1 = obj1.x + obj1.w;
		var t1 = obj1.y;
		var b1 = obj1.y + obj1.h;
	
		var l2 = obj2.x;
		var r2 = obj2.x + obj2.w;
		var t2 = obj2.y;
		var b2 = obj2.y + obj2.h;
	
		if (r1 > l2 && b1 > t2 && l1 < r2 && t1 < b2) {
			return true;
		} else {
			return false;
		}
	}
}

